#include "tcpforward.h"

TcpForward::TcpForward(QTcpSocket *clientSocket, QString serverIpAddr, unsigned short serverPortNum, QObject *parent)
{
    Q_UNUSED(parent);
    clientSd = clientSocket;
    serverIp = serverIpAddr;
    serverPort = serverPortNum;

    qDebug() << "New connection" << clientSd->peerAddress();

    serverSd = new QTcpSocket();
    if (serverSd == nullptr) {
        qDebug() << "Create socket to server failure.";
        return;
    }

    connect(serverSd, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error), this, &TcpForward::on_serverError);
    serverSd->connectToHost(serverIp, serverPort);

    connect(clientSd, &QTcpSocket::readyRead, this, &TcpForward::on_clientReadyRead);
    connect(clientSd, &QTcpSocket::disconnected, this, &TcpForward::on_clientDisconnect);

    connect(serverSd, &QTcpSocket::readyRead, this, &TcpForward::on_serverReadyRead);
    connect(serverSd, &QTcpSocket::disconnected, this, &TcpForward::on_serverDisconnect);

}

TcpForward::~TcpForward()
{
    if (serverSd != nullptr) {
        serverSd->close();
        delete serverSd;
        serverSd = nullptr;

        clientSd->close();
        delete clientSd;
        clientSd = nullptr;

        emit disconnect(this);
    }
}

void TcpForward::on_clientReadyRead()
{
    QByteArray data = clientSd->readAll();
    serverSd->write(data);

    emit uploadBytes(data.length());
}

void TcpForward::on_clientDisconnect()
{
    qDebug() << "Client " << clientSd->peerAddress() << ":" << clientSd->peerPort() << " disconnected.";
    deleteLater();
}

void TcpForward::on_serverReadyRead()
{
    QByteArray data = serverSd->readAll();
    clientSd->write(data);

    emit downloadBytes(data.length());
}

void TcpForward::on_serverDisconnect()
{
    qDebug() << "Server " << serverSd->peerAddress() << ":" << serverSd->peerPort() << " disconnected.";
    deleteLater();
}

void TcpForward::on_serverError(QAbstractSocket::SocketError socketError)
{
    switch (socketError) {
        case QAbstractSocket::HostNotFoundError:
            qDebug() << "The host was not found. Please check the host name and port settings.";
            break;
        case QAbstractSocket::ConnectionRefusedError:
            qDebug() << "The connection was refused by the peer. Make sure the fortune server is running, and check that the host name and port settings are correct.";
            break;
        default:
            qDebug() << "The following error occurred: " << serverSd->errorString();
    }

    if (clientSd != nullptr) {
        deleteLater();
    }
}
